import os, sys, zmq, traceback
import imp
from zmq.utils import jsonapi

from handlers.zmq import ZMQHandler, InvalidZMQObject

import log
from basedaemon import BaseDaemon

class AppServer(BaseDaemon):
	"""docstring for AppServer"""

	def __init__(self, pidfile, zmq_host, zmq_port, zmq_transport, zmq_debug, app_settings_file, **kwargs ):
		super(AppServer, self).__init__(pidfile, **kwargs)

		log.log("AppServer::__init__(pidfile:%s, zmq_host:%s, zmq_port:%s, zmq_transport:%s, app_settings_file:%s" % (
		  pidfile, zmq_host, zmq_port, zmq_transport, app_settings_file), 'info')

		self.transport = zmq_transport
		self.host = zmq_host
		self.port = zmq_port 
		self.debug = zmq_debug
		self.settings_file = app_settings_file

		self.context = None
		self.socket = None
		self.application = None
	#__init__()
		
	def run(self):
		"""docstring for run"""

		# import settings and get the application callable
		log.log("Import the settings file:%s" % (self.settings_file), 'debug')
		try:
			django_dmq = imp.load_source('django_dmq', self.settings_file)
			self.application = django_dmq.application
		except Exception as e:
			log.log("Unable to import application settings file:%s\n%s" % (self.settings_file, e), "error")
			raise

		# It's expected that the application settings file setup the
		# Django settings variable, so now we can import from Django
		from django.core.serializers.json import DjangoJSONEncoder

		self.context = zmq.Context()
		self.socket = self.context.socket(zmq.REP)
		device = '%s://%s:%s' % (self.transport, self.host, self.port)
		log.log("binding ZMQ to device:%s" % (device), 'info')
		self.socket.bind(device)

		environ = dict(os.environ.items())
		environ['ZMQ_HOST'] = self.host
		environ['ZMQ_PORT'] = self.port
		environ['ZMQ_TRANSPORT'] = self.transport
		environ['ZMQ_DEBUG'] = self.debug
		environ['DMQ_APPLICATION_SETTINGS_FILE'] = self.settings_file
		environ['SERVER_PORT'] = self.port

		run = True
		while run:
			orig_req = ""
			try:
				orig_req = self.socket.recv()

				log.log('AppServer::run() got orig_req:%s' % orig_req, 'debug')
				# We do the the heavy lifting in Django the extra
				# ZMQ* Django classes we add.
				# So this is pretty simple, call Django to process the request
				resp = self.application(environ, orig_req)
				# Responde with Django's reply. 
				# Simply requesting the response objects string will
				# get us its JSON encoding
				self.socket.send(str(resp))

			except Exception as e:
				log.log('AppServer::run() Got exception:%s\n%s' % (e, traceback.format_exc()),
						'error')
				msg = {'success':False, 'error_str':str(e),
					'orig_request':orig_req}
				self.socket.send(jsonapi.dumps(msg, cls=DjangoJSONEncoder))
	#run()
#AppServer
